package at.sm1.trainclassifier2000;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;

import at.sm1.trainclassifier2000.FeatureVector.FeatureType;

public class KMeans extends Classifier {

	private FeatureVector[] means; //0 = Railjet; 1 = Westbahn
	private int[] samples; //0 = Railjet; 1 = Westbahn
	private int maxSamples = 20;
	File inputFile;
	
	public KMeans(File inputFile)
	{
		this.inputFile = inputFile;
		
		means = new FeatureVector[2];
		means[0] = new FeatureVector();
		means[1] = new FeatureVector();
		
		samples = new int[2];
		
		try {
			BufferedReader in = new BufferedReader(new FileReader(inputFile));
			
			String line = "";
			while((line = in.readLine()) != null)
			{
				if(line.startsWith("#"))
					continue;
				if(line.startsWith("Railjet:"))
				{
					String featureLine = line.substring(line.indexOf(":")+1);
					String[] feature = featureLine.split(";");
					
					for(int i=0; i<feature.length; i++)
					{
						if(i < FeatureType.FEATURE_COUNT.getIndex())
							means[0].setFeature(FeatureType.getFeatureTypeFromIndex(i), Double.parseDouble(feature[i]));
						else
							samples[0] = Integer.parseInt(feature[i]);
					}
					
					continue;
				}
				if(line.startsWith("Westbahn:"))
				{
					String featureLine = line.substring(line.indexOf(":")+1);
					String[] feature = featureLine.split(";");
					
					for(int i=0; i<feature.length; i++)
					{
						if(i < FeatureType.FEATURE_COUNT.getIndex())
							means[1].setFeature(FeatureType.getFeatureTypeFromIndex(i), Double.parseDouble(feature[i]));
						else
							samples[1] = Integer.parseInt(feature[i]);
					}
					
					continue;
				}
			}
			
			in.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public ClassificationResult classify(FeatureVector v) {
		double distRail = v.getEuclideanDistance(means[0]);
		double distWest = v.getEuclideanDistance(means[1]);
		
		if(distRail < distWest)
			return ClassificationResult.RAILJET;
		
		if(distWest < distRail)
			return ClassificationResult.WESTBAHN;
		
		return ClassificationResult.UNDEFINED;
	}

	@Override
	public void classificationCheck(FeatureVector v, ClassificationResult r,
			boolean right) {
		switch(r)
		{
		case RAILJET:
			if(right)
			{
				changeMeanVector(0, v);
			}
			else
			{
				changeMeanVector(1, v);
			}
			break;
		case WESTBAHN:
			if(right)
			{
				changeMeanVector(1, v);
			}
			else
			{
				changeMeanVector(0, v);
			}
			break;
		default: return;
		}
		
		updateFile();
	}

	private void changeMeanVector(int index, FeatureVector rightVector)
	{
		means[index] = FeatureVector.interpolate(means[index],rightVector,Math.min((double)samples[index] / (double)maxSamples,0.8));
		samples[index]++;
	}
	
	private void updateFile()
	{
		try {
			PrintWriter out = new PrintWriter(inputFile);
			
			out.println("#KMeans - Input File");
			out.println("#BEGIN");
			out.println();
			
			out.print("Railjet:");
			
			for(int i=0; i<FeatureType.FEATURE_COUNT.getIndex(); i++)
			{
				out.print(Double.toString(means[0].getFeature(FeatureType.getFeatureTypeFromIndex(i)))+";");
			}
			
			out.print(Integer.toString(samples[0]));
			
			out.println();
			
			out.print("Westbahn:");
			
			for(int i=0; i<FeatureType.FEATURE_COUNT.getIndex(); i++)
			{
				out.print(Double.toString(means[1].getFeature(FeatureType.getFeatureTypeFromIndex(i)))+";");
			}
			
			out.print(Integer.toString(samples[1]));
			
			out.println();
			
			out.println("#END");
			
			out.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	public String toString()
	{
		return means[0].toString() + Integer.toString(samples[0]) + "\n" +
				means[1].toString() + Integer.toString(samples[1]);
	}
}
